package v1

import (
	"golang-microgrpc-sharemod/gateway-api/controllers"
	"golang-microgrpc-sharemod/gateway-api/utils"
	pbUser "golang-microgrpc-sharemod/services/user-service/proto/user"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

/*
 +----------------------------------------------------------------------
 + Title        : UserController
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2020-11-23
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 用户控制层
 +----------------------------------------------------------------------
*/
type UserController struct {
	controllers.BaseController
}

/**
 * 用户名登录
 *
 * @param string username -----------------------必传,用户名
 * @param string password -----------------------必传,密码
 * @return Json
 * @author huwl
 */
func (control UserController) Login(ctx *gin.Context) {
	username := ctx.DefaultPostForm("username", "")
	password := ctx.DefaultPostForm("password", "")
	if username == "" {
		control.BaseError(ctx, control.WithMessage("请输入用户名"))
		return
	}
	if password == "" {
		control.BaseError(ctx, control.WithMessage("请输入密码"))
		return
	}

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	userResult, err := userSrvClient.Row(ctx, &pbUser.QueryUserRequest{
		Username: username,
		Status:   "1",
	})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	if !utils.CompareBcrypt(userResult.User.Password, password) {
		control.BaseError(ctx, control.WithMessage("密码错误"))
		return
	}

	token, err := utils.GenerateToken(strconv.Itoa(int(userResult.User.Uid)))
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}

	// 生成refreshToken
	refreshToken := uuid.New().String()
	// 需要将refreshToken存入redis
	ri, err := utils.NewRedisInstance()
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}
	err = ri.RedisSet("userRefreshToken:"+strconv.FormatInt(userResult.User.Uid, 10), refreshToken, time.Hour*12*10)
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}

	control.BaseSuccess(ctx, control.WithData(gin.H{
		"user":              userResult.User,
		"token":             token,
		"token_expire_time": time.Now().Add(utils.TokenExpireTime).Unix(),
		"refresh_token":     refreshToken,
	}), control.WithMessage("登录成功"))
}

/**
 * 手机号登录
 *
 * @param string mobile -------------------------必传,手机号
 * @param string code ---------------------------必传,验证码
 * @return Json
 * @author huwl
 */
func (control UserController) MobileLogin(ctx *gin.Context) {
	mobile := ctx.DefaultPostForm("mobile", "")
	code := ctx.DefaultPostForm("code", "")

	if mobile == "" {
		control.BaseError(ctx, control.WithMessage("请输入手机号"))
		return
	}
	if !utils.CheckMobile(mobile) {
		control.BaseError(ctx, control.WithMessage("请输入格式正确的手机号"))
		return
	}
	if code == "" {
		control.BaseError(ctx, control.WithMessage("请输入验证码"))
		return
	}

	// 校验验证码
	ri, err := utils.NewRedisInstance()
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}
	redisCode, _ := ri.RedisGet("login_code_" + mobile)
	if redisCode != code {
		control.BaseError(ctx, control.WithMessage("验证码错误"))
		return
	}

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	userResult, err := userSrvClient.Row(ctx, &pbUser.QueryUserRequest{
		Mobile: mobile,
		Status: "1",
	})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	// 生成token
	token, err := utils.GenerateToken(strconv.Itoa(int(userResult.User.Uid)))
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}

	// 生成refreshToken
	refreshToken := uuid.New().String()
	// 需要将refreshToken存入redis
	err = ri.RedisSet("userRefreshToken:"+strconv.FormatInt(userResult.User.Uid, 10), refreshToken, time.Hour*12*10)
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}

	control.BaseSuccess(ctx, control.WithData(gin.H{
		"user":              userResult.User,
		"token":             token,
		"token_expire_time": time.Now().Add(utils.TokenExpireTime).Unix(),
		"refresh_token":     refreshToken,
	}), control.WithMessage("登录成功"))
}

/**
 * 发送验证码
 *
 * @param string mobile ------------------------必传,手机号
 * @return Json
 * @author huwl
 */
func (control UserController) LoginSendCode(ctx *gin.Context) {
	mobile := ctx.DefaultPostForm("mobile", "")
	if mobile == "" {
		control.BaseError(ctx, control.WithMessage("请输入手机号"))
		return
	}
	if !utils.CheckMobile(mobile) {
		control.BaseError(ctx, control.WithMessage("请输入格式正确的手机号"))
		return
	}

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	_, err := userSrvClient.Row(ctx, &pbUser.QueryUserRequest{
		Mobile: mobile,
		Status: "1",
	})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	// 生成、存储 验证码
	// time.Second*300 过期时间5分钟
	code := utils.CreateRandNum(100000, 400000)
	ri, err := utils.NewRedisInstance()
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}
	err = ri.RedisSet("login_code_"+mobile, code, time.Second*300)
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}

	// 发送短信
	err = utils.SendSms(mobile, "verificationCodeTemplate", map[string]interface{}{"code": code})
	if err != nil {
		control.BaseError(ctx, control.WithMessage(err.Error()))
		return
	}

	control.BaseSuccess(ctx, control.WithData("发送验证码成功"))
}

/**
 * 注册
 *
 * @param string username -----------------------必传,用户名
 * @param string password -----------------------必传,密码
 * @param string repassword ---------------------必传,重复密码
 * @param string mobile -------------------------必传,手机号
 * @param string email --------------------------必传,邮箱
 * @param string captcha ------------------------必传,验证码
 * @param string captcha_id ---------------------必传,验证码ID
 * @return Json
 * @author huwl
 */
func (control UserController) Register(ctx *gin.Context) {
	username := ctx.DefaultPostForm("username", "")
	password := ctx.DefaultPostForm("password", "")
	repassword := ctx.DefaultPostForm("repassword", "")
	mobile := ctx.DefaultPostForm("mobile", "")
	email := ctx.DefaultPostForm("email", "")
	// captcha := ctx.DefaultPostForm("captcha", "")
	// captchaId := ctx.DefaultPostForm("captcha_id", "")

	if username == "" {
		control.BaseError(ctx, control.WithMessage("请输入用户名"))
		return
	}
	if password == "" {
		control.BaseError(ctx, control.WithMessage("请输入密码"))
		return
	}
	if repassword == "" {
		control.BaseError(ctx, control.WithMessage("请输入确认密码"))
		return
	}
	if password != repassword {
		control.BaseError(ctx, control.WithMessage("两次密码要输入一致哦"))
		return
	}
	if !utils.CheckMobile(mobile) {
		control.BaseError(ctx, control.WithMessage("请输入正确格式的手机号"))
		return
	}
	if !utils.CheckEmail(email) {
		control.BaseError(ctx, control.WithMessage("请输入正确格式的邮箱"))
		return
	}

	//判断验证码
	// b := utils.ValidateCaptcha(captchaId, captcha)
	// if !b {
	// 	control.BaseError(ctx, "验证码错误")
	// 	return
	// }

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	_, err := userSrvClient.AddUser(ctx, &pbUser.AddUserRequest{
		Username: username,
		Password: password,
		Mobile:   mobile,
		Email:    email,
		Status:   1,
	})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	control.BaseSuccess(ctx, control.WithData("用户注册成功"))
}

func (control UserController) Edit(ctx *gin.Context) {

}

/**
 * 用户详情
 *
 * @param int uid -------------------------------非必传,uid
 * @return Json
 * @author huwl
 */
func (control UserController) Detail(ctx *gin.Context) {
	uid, _ := ctx.Get("uid")
	userId, _ := strconv.ParseInt(uid.(string), 10, 64)
	if userId <= 0 {
		userId, _ = strconv.ParseInt(ctx.DefaultQuery("uid", "0"), 10, 64)
	}

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	result, err := userSrvClient.UserDetail(ctx, &pbUser.UserDetailRequest{Uid: userId})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	control.BaseSuccess(ctx, control.WithData(gin.H{
		"user":        result.User,
		"user_albums": result.UserAlbums,
	}))
}

/**
 * 用户列表
 *
 * @param int uid -------------------------------非必传,用户Id
 * @param string uids ---------------------------非必传,用户Id多个
 * @param string name ---------------------------非必传,姓名
 * @param string nick ---------------------------非必传,昵称
 * @param string email --------------------------非必传,邮箱
 * @param string username -----------------------非必传,用户名
 * @param int source ----------------------------非必传,来源
 * @param int level -----------------------------非必传,级别
 * @param string mobile -------------------------非必传,手机号
 * @param int gender ----------------------------非必传,性别
 * @param int province_id -----------------------非必传,省Id
 * @param int city_id ---------------------------非必传,市Id
 * @param int district_id -----------------------非必传,区Id
 * @param string status -------------------------非必传,状态
 * @param string start_create_time --------------非必传,开始创建时间
 * @param string end_create_time ----------------非必传,结束创建时间
 * @param string sort_field ---------------------非必传,排序字段
 * @param string sort_type ----------------------非必传,排序方式
 * @param int page_size -------------------------非必传,条数
 * @param int page ------------------------------非必传,页码
 * @return Json
 * @author huwl
 */
func (control UserController) List(ctx *gin.Context) {
	uid, _ := strconv.Atoi(ctx.DefaultPostForm("uid", "0"))
	uids := ctx.DefaultQuery("uids", "")
	name := ctx.DefaultQuery("name", "")
	nick := ctx.DefaultQuery("nick", "")
	email := ctx.DefaultQuery("email", "")
	username := ctx.DefaultQuery("username", "")
	source, _ := strconv.Atoi(ctx.DefaultPostForm("source", "0"))
	level, _ := strconv.Atoi(ctx.DefaultPostForm("level", "0"))
	mobile := ctx.DefaultQuery("mobile", "")
	provinceId, _ := strconv.Atoi(ctx.DefaultPostForm("province_id", "0"))
	cityId, _ := strconv.Atoi(ctx.DefaultPostForm("city_id", "0"))
	districtId, _ := strconv.Atoi(ctx.DefaultPostForm("district_id", "0"))
	status := ctx.DefaultQuery("status", "all")
	startCreateTime := ctx.DefaultQuery("start_create_time", "")
	endCreateTime := ctx.DefaultQuery("end_create_time", "")
	sortField := ctx.DefaultQuery("sort_field", "")
	sortType := ctx.DefaultQuery("sort_type", "")
	page, _ := strconv.Atoi(ctx.DefaultPostForm("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultPostForm("page_size", "20"))

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	result, err := userSrvClient.UserList(ctx, &pbUser.QueryUserRequest{
		Uid:             int64(uid),
		Uids:            uids,
		Name:            name,
		Nick:            nick,
		Email:           email,
		Username:        username,
		Source:          uint32(source),
		Level:           uint32(level),
		Mobile:          mobile,
		ProvinceId:      uint32(provinceId),
		CityId:          uint32(cityId),
		DistrictId:      uint32(districtId),
		Status:          status,
		StartCreateTime: startCreateTime,
		EndCreateTime:   endCreateTime,
		SortField:       sortField,
		SortType:        sortType,
		Page:            uint32(page),
		PageSize:        int32(pageSize),
	})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	control.BaseSuccess(ctx, control.WithData(gin.H{
		"page":       result.ListResult.Page,
		"page_total": result.ListResult.PageTotal,
		"total":      result.ListResult.Total,
		"users":      result.Users,
	}))
}

/**
 * 数量
 *
 * @param int uid -------------------------------非必传,用户Id
 * @param string uids ---------------------------非必传,用户Id多个
 * @param string name ---------------------------非必传,姓名
 * @param string nick ---------------------------非必传,昵称
 * @param string email --------------------------非必传,邮箱
 * @param string username -----------------------非必传,用户名
 * @param int source ----------------------------非必传,来源
 * @param int level -----------------------------非必传,级别
 * @param string mobile -------------------------非必传,手机号
 * @param int gender ----------------------------非必传,性别
 * @param int province_id -----------------------非必传,省Id
 * @param int city_id ---------------------------非必传,市Id
 * @param int district_id -----------------------非必传,区Id
 * @param string status -------------------------非必传,状态
 * @param string start_create_time --------------非必传,开始创建时间
 * @param string end_create_time ----------------非必传,结束创建时间
 * @return Json
 * @author huwl
 */
func (control UserController) Total(ctx *gin.Context) {
	uid, _ := strconv.Atoi(ctx.DefaultPostForm("uid", "0"))
	uids := ctx.DefaultQuery("uids", "")
	name := ctx.DefaultQuery("name", "")
	nick := ctx.DefaultQuery("nick", "")
	email := ctx.DefaultQuery("email", "")
	username := ctx.DefaultQuery("username", "")
	source, _ := strconv.Atoi(ctx.DefaultPostForm("source", "0"))
	level, _ := strconv.Atoi(ctx.DefaultPostForm("level", "0"))
	mobile := ctx.DefaultQuery("mobile", "")
	provinceId, _ := strconv.Atoi(ctx.DefaultPostForm("province_id", "0"))
	cityId, _ := strconv.Atoi(ctx.DefaultPostForm("city_id", "0"))
	districtId, _ := strconv.Atoi(ctx.DefaultPostForm("district_id", "0"))
	status := ctx.DefaultQuery("status", "all")
	startCreateTime := ctx.DefaultQuery("start_create_time", "")
	endCreateTime := ctx.DefaultQuery("end_create_time", "")

	// grpc远程调用用户微服务
	userSrvClient := pbUser.NewUserSrvClient(utils.UserServiceClientConn)
	result, err := userSrvClient.UserTotal(ctx, &pbUser.QueryUserRequest{
		Uid:             int64(uid),
		Uids:            uids,
		Name:            name,
		Nick:            nick,
		Email:           email,
		Username:        username,
		Source:          uint32(source),
		Level:           uint32(level),
		Mobile:          mobile,
		ProvinceId:      uint32(provinceId),
		CityId:          uint32(cityId),
		DistrictId:      uint32(districtId),
		Status:          status,
		StartCreateTime: startCreateTime,
		EndCreateTime:   endCreateTime,
	})
	if err != nil {
		control.BaseError(ctx, control.WithGrpcError(err))
		return
	}

	control.BaseSuccess(ctx, control.WithData(gin.H{
		"total": result.Total,
	}))
}
